@page "/account/loginwith2fa"

@layout LoginLayout
@inject NavigationManager navigationManager
@inject AuthenticationStateProvider authStateProvider
@inject IMatToaster matToaster
@inject AppState appState
@inject NavigationManager NavigationManager
@inject IJSRuntime js
@inject IStringLocalizer<Global> L

<AuthorizeView Context="AuthorizeContext">
    <Authorized>
        <LoadingBackground ShowLogoBox="true">
            <label>@L["Loading"]</label>
        </LoadingBackground>
    </Authorized>
    <NotAuthorized>
        @if (RedirectInProgress)
        {
            <LoadingBackground ShowLogoBox="true">
                <label>@L["Loading"]</label>
            </LoadingBackground>
        }
        else
        {
            <MatCard>
                <div class="hidden-mdc-down">
                    <MatIconButton Icon="home" Class="float-left" Link="/" />
                </div>
                <div class="logo">
                    <a href="/" title="@appState.AppName Home"><img src="_content/BlazorBoilerplate.Theme.Material/images/logo.svg" style="width:100px;" title="@appState.AppName Home" alt="@appState.AppName" /><br />@appState.AppName</a>
                    <br />
                    <h4>@L["Log in"]</h4>
                </div>
                <EditForm Model="@loginViewModel" OnValidSubmit="@SubmitLogin">
                    <FluentValidationValidator />
                    <ValidationSummary />
                    <fieldset>
                        <div class="form-group">
                            <MatTextField id="code" @bind-Value="@loginViewModel.TwoFactorCode" Label=@L["Code"] Icon="lock_outline" IconTrailing="true" FullWidth="true" Required="true" Type="password" tabindex="1"></MatTextField>
                        </div>
                        <div class="form-group">
                            <MatButton class="float-right" Type="submit" Raised="true" tabindex="2">@L["Login"]</MatButton>
                            <MatCheckbox @bind-Value="@loginViewModel.RememberMachine" class="filled-in chk-col-blue">@L["RememberBrowser"]</MatCheckbox>
                        </div>
                    </fieldset>
                </EditForm>
            </MatCard>
            <MatAccordion>
                <MatExpansionPanel @bind-Expanded="@forgotAuthenticatorToggle">
                    <MatExpansionPanelSummary>
                        <MatExpansionPanelHeader>@L["ForgotAuthenticator"]</MatExpansionPanelHeader>
                        <MatExpansionPanelSubHeader></MatExpansionPanelSubHeader>
                    </MatExpansionPanelSummary>
                    <MatExpansionPanelDetails>
                        <EditForm Model="@forgotAuthenticatorInputModel" OnValidSubmit="@ForgotAuthenticator">
                            <FluentValidationValidator />
                            <ValidationSummary />
                            <div class="form-group">
                                <MatTextField @bind-Value="@forgotAuthenticatorInputModel.RecoveryCode" Label=@L["RecoveryCode"] Icon="lock_outline" IconTrailing="true" FullWidth="true" Required="true" Type="password"></MatTextField>
                            </div>
                            <div class="form-group">
                                <MatButton class="float-right" Type="submit" Raised="true">@L["Login"]</MatButton>
                            </div>
                        </EditForm>
                    </MatExpansionPanelDetails>
                </MatExpansionPanel>
            </MatAccordion>
        }
    </NotAuthorized>
</AuthorizeView>
@code {

    string navigateTo = null;
    IdentityAuthenticationStateProvider identityAuthenticationStateProvider;
    bool forgotAuthenticatorToggle = false;
    bool RedirectInProgress = false;
    static bool LoginSuccess = false;
    LoginWith2faInputModel loginViewModel { get; set; } = new LoginWith2faInputModel();
    LoginWithRecoveryCodeInputModel forgotAuthenticatorInputModel { get; set; } = new LoginWithRecoveryCodeInputModel();

    string ReturnUrl;

    protected override async Task OnInitializedAsync()
    {
        if (navigationManager.TryGetQueryString<string>("ReturnUrl", out string url))
            ReturnUrl = url;

        var user = (await authenticationStateTask).User;

        if (user.Identity.IsAuthenticated || LoginSuccess)
            RedirectInProgress = true;
        else
            identityAuthenticationStateProvider = (IdentityAuthenticationStateProvider)authStateProvider;

        LoginSuccess = false;
    }

    [CascadingParameter]
    Task<AuthenticationState> authenticationStateTask { get; set; }


    protected override async Task OnParametersSetAsync()
    {
        if (navigationManager.IsWebAssembly())
        {
            var user = (await authenticationStateTask).User;

            if (user.Identity.IsAuthenticated && navigateTo != null)
                navigationManager.NavigateTo(navigateTo);
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && !RedirectInProgress)
            await js.InvokeVoidAsync("interop.SetFocus", "code");

        await base.OnAfterRenderAsync(firstRender);
    }

    async Task SubmitLogin()
    {
        try
        {
            loginViewModel.ReturnUrl = ReturnUrl;
            var response = await identityAuthenticationStateProvider.LoginWith2fa(loginViewModel);

            await PostLoginProcess(response);
        }
        catch (Exception ex)
        {
            matToaster.Add(ex.Message, MatToastType.Danger, L["LoginFailed"]);
        }
    }

    async Task ForgotAuthenticator()
    {
        try
        {
            forgotAuthenticatorInputModel.ReturnUrl = ReturnUrl;
            var response = await identityAuthenticationStateProvider.LoginWithRecoveryCode(forgotAuthenticatorInputModel);

            await PostLoginProcess(response);
        }
        catch (Exception ex)
        {
            matToaster.Add(ex.Message, MatToastType.Danger, L["LoginFailed"]);
        }
    }

    async Task PostLoginProcess(ApiResponseDto response)
    {
        if (response.IsSuccessStatusCode)
        {
            if (navigationManager.IsWebAssembly())
            {
                if (string.IsNullOrEmpty(ReturnUrl))
                {
                    var userProfile = await appState.GetUserProfile();

                    navigateTo = navigationManager.BaseUri + (!string.IsNullOrEmpty(userProfile?.LastPageVisited) ? userProfile?.LastPageVisited : "/dashboard");
                }
                else
                    navigateTo = ReturnUrl;

                navigationManager.NavigateTo(navigateTo);
            }
            else
                RedirectInProgress = true;

            LoginSuccess = true;
        }
        else
            matToaster.Add(response.Message, MatToastType.Danger, L["LoginFailed"]);
    }
}
